#include "InputStream.hpp"

int libInputStream::InitInputStream(libIntelligentParser *_IP)
{
    if (NULL == _IP)
    {
        PrintLog("Failed assign Input_URL. INDEX_5");
        return -1;
    }
    IP = _IP;
    if (0 == IP->CI.IN_URL.length())
    {
        return -1;
    }
    cout << "输入链接：" << IP->CI.IN_URL << endl;
    //启动输入
    if (input_ctx == NULL)
    {
        input_ctx = avformat_alloc_context();
        if (!input_ctx)
        {
            PrintLog("Failed avformat_alloc_context. INDEX_314651");
            return -1;
        }
    }
    now_time = last_time = time(NULL);//time 
    input_ctx->interrupt_callback.callback = libInputStream::interrupt_ic; //
    input_ctx->interrupt_callback.opaque = input_ctx;
    int ret = avformat_open_input(&input_ctx, IP->CI.IN_URL.c_str(), NULL, NULL);
    while (0 != ret)  
    {
        Sleep(6000);
        PrintLog("Failed avformat_open_input. INDEX_6987965");
        ret = avformat_open_input(&input_ctx, IP->CI.IN_URL.c_str(), NULL, NULL);
    }
    if (avformat_find_stream_info(input_ctx, NULL) < 0)
    {
        PrintLog("Could not read stream information .INDEX_45386");
        avformat_flush(input_ctx);  //
        avformat_close_input(&input_ctx);
//        avformat_free_context(input_ctx);
        return -1;
    }
    //配置libIntelligentParser
    ret = IP->SetParamFromAVFormatContext(input_ctx);
    if (ret != 0)
    {
        PrintLog("Failed SetParamFromAVFormatContext. INDEX_358754");
        return -1;
    }
    now_time = last_time = time(NULL);//
    //begin input thread
    StartInputStreamThread(); 

    return 0;
}

int libInputStream::StartInputStreamThread()
{
    thread t_input(Thread_InputStream, this);
    t_input.detach();
    WriteLog("Input begin! INDEX_6");
    return 0;
}

void libInputStream::Thread_InputStream(void *p_this)
{
    libInputStream *l = (libInputStream*)p_this;
    return l->Thread_InputStreamm();
}

void libInputStream::Thread_InputStreamm()
{
    int ret; 
    int v_stream_index = IP->input_video_stream_index;
    int a_stream_index = IP->input_audio_stream_index;
    AVCodecParameters *codecpar = IP->input_video_codecpar;
    int v_format = codecpar->format;
    int v_width = codecpar->width;
    int v_height = codecpar->height;

    codecpar = IP->input_audio_codecpar;
    int a_sample_format = codecpar->format;
    int a_nb_samples = codecpar->frame_size; //1024
    int a_channel = codecpar->channels;
    //video codeccontext    
    AVCodecContextPP v_codecctx;
    if (v_codecctx.SetDecodecCtx(IP->input_video_codecpar) != 0)
    {
        PrintLog("Failed SetDecodecCtx. INDEX_887");
        return;
    }
    //audio codeccontext
    AVCodecContextPP a_codecctx;
    if (a_codecctx.SetDecodecCtx(IP->input_audio_codecpar) != 0)
    {
        PrintLog("Failed SetDecodecCtx. INDEX_888");
        return;
    }
    av_dump_format(input_ctx, 0, IP->CI.IN_URL.c_str(), 0);
    //
    AVPacketPP packet;
    while (true)
    {
        b_thread_flag = true;
        packet.unref();
        int64_t frame_pts;

        ret = av_read_frame(input_ctx, packet.packet);
        if (ret < 0)
        {
            break; //直接关闭
        }
        last_time = now_time;//for interrupt_ic
        //////////////////////////////////////////////////////////////////////////
        if (packet.packet->stream_index == v_stream_index)
        {
            AVFramePP frame_video;
            if (v_codecctx.DecodecPacket(packet.packet, frame_video.frame) != 0)
            {
                continue;
            }
            frame_pts = av_frame_get_best_effort_timestamp(frame_video.frame); //不清楚用处大不大
            if (frame_pts == AV_NOPTS_VALUE)
            {
                frame_pts = frame_video.frame->pkt_pts;
            }
            ret = IP->WriteVideoFrame(frame_video.frame);
            if (ret != 0) //error
            {
                PrintLog("Failed WriteVideoFrame. INDEX_22");
            }
        }
        else if (packet.packet->stream_index == a_stream_index)
        {
            AVFramePP frame_audio;
            if (a_codecctx.DecodecPacket(packet.packet, frame_audio.frame) != 0)
            {
                continue;
            }        
            frame_pts = av_frame_get_best_effort_timestamp(frame_audio.frame); 
            if (frame_pts==AV_NOPTS_VALUE)
            {
                frame_pts = frame_audio.frame->pkt_pts;
            }
            ret = IP->WriteAudioFrame(frame_audio.frame);
            if (ret != 0) //error
            {
                PrintLog("Failed WriteAudioFrame.INDEX_23");
            }
        }
    }

    avformat_flush(input_ctx);
    avformat_close_input(&input_ctx);
    b_thread_flag = false;

    WriteTXT("State.in", "stop");//似乎直接拔电源后 没执行这一步来
}

int libInputStream::interrupt_ic(void *_ctx)
{
    now_time = time(NULL);
    if ((now_time - last_time) > 20) // 20 second  似乎在avformat_open_input之后就会开始计时 留意一下
    {
        printf("Input stream interrupt !\n");
        return 1;
    }
    return 0;
}

bool libInputStream::GetInputStatus()
{
    bool b_local = b_thread_flag;
    return b_local;
}
